<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>基层AI辅助诊断系统 - 角色管理</title>
    <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
    <script src="https://unpkg.com/vue@3"></script>
    <script src="https://unpkg.com/element-plus"></script>
    <script src="https://unpkg.com/element-plus/dist/locale/zh-cn.min.js"></script>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
            background: #FFFFFF; color: var(--text-primary); font-size: 14px; line-height: 1.5; margin: 0;
        }
        :root {
            --primary: #0F6CBD; --primary-light: #D0E7FF; --primary-dark: #0A4F8D;
            --success: #0F8A5F; --warning: #F59337; --error: #D13438; --info: #0078D4;
            --text-primary: #1A1A1A; --text-secondary: #4D4D4D; --text-tertiary: #767676; --text-disabled: #A6A6A6;
            --border-strong: #CCCCCC; --border-normal: #E0E0E0; --border-light: #F0F0F0; --divider: #F5F5F5;
            --bg-primary: #FFFFFF; --bg-secondary: #F9F9F9; --bg-card: #FFFFFF; --bg-disabled: #F5F5F5;
            --spacing-2: 2px; --spacing-4: 4px; --spacing-8: 8px; --spacing-12: 12px; --spacing-16: 16px; --spacing-24: 24px; --spacing-32: 32px; --spacing-40: 40px; --spacing-48: 48px;
            --font-page-title: 20px; --font-card-title: 16px; --font-table-title: 14px; --font-body: 14px; --font-table: 13px; --font-small: 12px;
            --line-height-title: 1.4; --line-height-body: 1.5; --line-height-table: 1.2; --line-height-form: 1.4;
            --radius-small: 2px; --radius-medium: 4px;
            --transition-fast: 150ms; --transition-normal: 200ms; --transition-slow: 300ms;
            --nav-item-width: 140px;
        }
        .container { width: 100%; min-height: 100vh; display: flex; flex-direction: column; background-color: var(--bg-secondary); }
        .header { height: 60px; background-color: var(--bg-primary); border-bottom: 1px solid var(--border-normal); display: flex; align-items: center; padding: 0 var(--spacing-24); box-shadow: 0 2px 4px rgba(0,0,0,0.05); position: relative; z-index: 100; }
        .header-spacer { width: 200px; flex-shrink: 0; }
        #app-nav { position: absolute; left: 50%; transform: translateX(-50%); z-index: 10; width: calc(100% - 400px); display: flex; justify-content: center; }
        .el-menu { border: none !important; background-color: transparent !important; }
        .el-menu--horizontal > .el-menu-item,
        .el-menu--horizontal > .el-sub-menu .el-sub-menu__title { height: 60px; line-height: 60px; color: var(--text-secondary); font-weight: 500; font-size: var(--font-body); padding: 0; width: var(--nav-item-width); text-align: center; display: flex; align-items: center; justify-content: center; position: relative; }
        .el-sub-menu__icon-arrow { display: none !important; }
        .el-menu--horizontal > .el-sub-menu .el-sub-menu__title::after { content: ''; display: inline-block; width: 16px; height: 16px; margin-left: 8px; background-repeat: no-repeat; background-position: center; background-size: 16px 16px; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23767676' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>"); }
        .el-sub-menu:hover > .el-sub-menu__title::after, .el-sub-menu.is-active > .el-sub-menu__title::after { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%230F6CBD' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>"); }
        .el-sub-menu.is-opened > .el-sub-menu__title::after { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%230F6CBD' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 15 12 9 18 15'/></svg>"); }
        .el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-sub-menu.is-active .el-sub-menu__title { color: var(--primary) !important; border-bottom: 2px solid var(--primary); font-weight: 500; }
        .el-menu--horizontal > .el-menu-item:not(.is-disabled):hover,
        .el-menu--horizontal > .el-menu-item:not(.is-disabled):focus,
        .el-menu--horizontal > .el-sub-menu:not(.is-disabled):hover .el-sub-menu__title { color: var(--primary); background-color: transparent; }
        .el-menu--popup { width: var(--nav-item-width) !important; min-width: var(--nav-item-width) !important; max-width: var(--nav-item-width) !important; border-radius: var(--radius-small); padding: 4px 0; border: 1px solid var(--border-light); border-top: 2px solid var(--primary); box-shadow: 0 2px 8px rgba(0,0,0,0.1); text-align: center !important; }
        .el-menu--popup .el-menu-item { height: 36px; line-height: 36px; padding: 0 !important; color: var(--text-secondary); white-space: nowrap; text-align: center; width: var(--nav-item-width) !important; box-sizing: border-box; overflow: hidden; text-overflow: ellipsis; display: flex !important; justify-content: center !important; align-items: center !important; font-size: var(--font-body); }
        .el-menu--popup .el-menu-item:hover { background-color: var(--bg-secondary); color: var(--primary); }
        .user-section { display: flex; align-items: center; gap: var(--spacing-16); margin-left: auto; z-index: 10; width: 200px; justify-content: flex-end; flex-shrink: 0; cursor: pointer; padding: 8px 12px; border-radius: var(--radius-small); transition: background-color var(--transition-fast); color: var(--text-secondary); }
        .user-section:hover { background-color: var(--bg-secondary); }
        .user-name { font-weight: 500; font-size: var(--font-body); color: var(--text-secondary); }
        .user-arrow { color: var(--text-tertiary); transition: color var(--transition-normal); }
        .user-section:hover .user-arrow { color: var(--primary); }

        .main-content { padding: 0; flex: 1; background-color: var(--bg-primary); width: 100%; }
        .combined-header { display: flex; justify-content: space-between; align-items: center; padding: var(--spacing-24); border-bottom: 1px solid var(--border-light); background-color: var(--bg-primary); }
        .page-title { font-size: var(--font-page-title); font-weight: 600; color: var(--text-primary); line-height: var(--line-height-title); margin-right: var(--spacing-24); white-space: nowrap; }
        .filter-container { display: flex; align-items: center; gap: var(--spacing-16); flex-wrap: nowrap; }
        .search-box { position: relative; width: 240px; }
        .search-icon { position: absolute; left: 8px; top: 50%; transform: translateY(-50%); color: var(--text-tertiary); pointer-events: none; }
        .search-box input { width: 100%; padding: var(--spacing-8) var(--spacing-8) var(--spacing-8) 32px; border: 1px solid var(--border-normal); border-radius: var(--radius-small); font-size: 14px; color: var(--text-primary); transition: border-color 0.2s, box-shadow 0.2s; height: 32px; }
        .search-box input:focus { border-color: var(--primary); outline: none; box-shadow: 0 0 0 2px rgba(15,108,189,0.2); }
        .select { height: 32px; border: 1px solid var(--border-normal); border-radius: var(--radius-small); padding: 0 var(--spacing-12); font-size: var(--font-body); color: var(--text-primary); }
        .btn { padding: var(--spacing-8) var(--spacing-16); border-radius: var(--radius-small); font-size: var(--font-body); font-weight: 500; cursor: pointer; border: none; display: inline-flex; align-items: center; justify-content: center; transition: all var(--transition-normal); gap: var(--spacing-8); height: 32px; line-height: 1; }
        .btn-primary { background-color: var(--primary); color: #fff; }
        .btn-primary:hover { background-color: var(--primary-dark); }
        .btn-default { background-color: var(--bg-primary); color: var(--text-secondary); border: 1px solid var(--border-normal); }
        .btn-default:hover { background-color: var(--bg-secondary); }

        .table-section { padding: var(--spacing-24); display: flex; flex-direction: column; gap: var(--spacing-24); background-color: var(--bg-primary); }
        .table-container { background-color: var(--bg-primary); border-radius: var(--radius-small); box-shadow: 0 1px 3px rgba(0,0,0,0.05); overflow: auto; margin-bottom: var(--spacing-16); border: 1px solid var(--border-light); }
        .data-table { width: 100%; border-collapse: collapse; }
        .data-table th { background-color: var(--bg-secondary); padding: var(--spacing-12) var(--spacing-16); text-align: left; font-weight: 600; color: var(--text-secondary); border-bottom: 1px solid var(--border-normal); height: 40px; font-size: var(--font-table-title); }
        .data-table td { padding: var(--spacing-12) var(--spacing-16); border-bottom: 1px solid var(--border-light); color: var(--text-secondary); height: 40px; vertical-align: middle; font-size: var(--font-table); }
        .data-table tr:hover { background-color: var(--bg-secondary); }
        .operations { display: inline-flex; gap: var(--spacing-8); }
        .operation-link { color: var(--primary); text-decoration: none; cursor: pointer; }
        .operation-link:hover { color: var(--primary-dark); }
        .empty-table-message { text-align: center; color: var(--text-tertiary); padding: var(--spacing-16); font-style: italic; }

        .table-footer { display: flex; justify-content: space-between; align-items: center; padding: var(--spacing-16) var(--spacing-24); }
        .pagination-text { color: var(--text-tertiary); font-size: var(--font-small); }
        .pagination-controls { display: flex; align-items: center; gap: var(--spacing-24); }
        .page-numbers { display: flex; gap: var(--spacing-8); }
        .page-numbers button { min-width: 32px; height: 32px; border-radius: var(--radius-small); border: 1px solid var(--border-normal); background: var(--bg-primary); cursor: pointer; color: var(--text-secondary); transition: all var(--transition-normal); display: flex; align-items: center; justify-content: center; font-size: var(--font-small); }
        .page-numbers button:hover { border-color: var(--primary); color: var(--primary); }
        .page-numbers button.active { background: var(--primary); border-color: var(--primary); color: #FFFFFF; }
        .pagination-size { display: flex; align-items: center; gap: var(--spacing-8); color: var(--text-secondary); font-size: var(--font-small); }
        .page-size-selector { height: 32px; border: 1px solid var(--border-normal); border-radius: var(--radius-small); padding: 0 var(--spacing-8); font-size: var(--font-small); margin: 0 var(--spacing-4); }

        /* 弹窗通用 */
        .modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); display: none; align-items: center; justify-content: center; z-index: 1000; }
        .modal { background-color: var(--bg-primary); border-radius: var(--radius-small); box-shadow: 0 4px 16px rgba(0,0,0,0.1); width: 720px; max-width: 90%; max-height: 90vh; display: flex; flex-direction: column; overflow: hidden; }
        .modal-header { padding: var(--spacing-16) var(--spacing-24); border-bottom: 1px solid var(--border-light); display: flex; align-items: center; justify-content: space-between; }
        .modal-title { font-size: var(--font-card-title); font-weight: 600; color: var(--text-primary); }
        .modal-close { background: none; border: none; cursor: pointer; color: var(--text-tertiary); font-size: 20px; display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; }
        .modal-close:hover { background-color: var(--bg-secondary); color: var(--text-secondary); }
        .modal-body { padding: var(--spacing-24); overflow-y: auto; }
        .modal-footer { padding: var(--spacing-16) var(--spacing-24); border-top: 1px solid var(--border-light); display: flex; justify-content: flex-end; gap: var(--spacing-16); }

        /* 角色编辑弹窗 */
        .form-group { margin-bottom: var(--spacing-16); }
        .form-label { display: block; margin-bottom: var(--spacing-8); font-weight: 500; color: var(--text-secondary); }
        .form-control { width: 100%; padding: var(--spacing-8) var(--spacing-12); border: 1px solid var(--border-normal); border-radius: var(--radius-small); font-size: var(--font-body); color: var(--text-primary); transition: border-color var(--transition-normal); height: 36px; }
        .form-control:focus { border-color: var(--primary); outline: none; box-shadow: 0 0 0 2px rgba(15,108,189,0.2); }
        textarea.form-control { min-height: 100px; resize: vertical; }

        /* 权限管理弹窗（全屏、无缝左右栏） */
        .fullscreen { width: 92vw; height: 88vh; max-width: 1280px; }
        .perm-layout { display: grid; grid-template-columns: 320px 1fr; height: 100%; }
        .perm-left { border-right: 1px solid var(--border-light); overflow: auto; }
        .perm-right { overflow: auto; }
        .perm-header { padding: var(--spacing-16) var(--spacing-24); border-bottom: 1px solid var(--border-light); display: flex; align-items: center; justify-content: space-between; }
        .tree { padding: var(--spacing-16) var(--spacing-16); }
        .tree-item { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: var(--radius-small); cursor: pointer; color: var(--text-secondary); user-select: none; }
        .tree-item:hover { background-color: var(--bg-secondary); }
        .tree-item.active { background-color: var(--primary-light); color: var(--primary); font-weight: 500; }
        .tree-arrow { display: inline-block; width: 16px; height: 16px; flex-shrink: 0; background-repeat: no-repeat; background-position: center; background-size: 16px 16px; }
        .tree-arrow[data-expanded="true"] { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%230F6CBD' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 15 12 9 18 15'/></svg>"); }
        .tree-arrow[data-expanded="false"] { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%230F6CBD' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>"); }
        .tree-spacer { display: inline-block; width: 16px; height: 16px; flex-shrink: 0; }
        .perm-section { padding: var(--spacing-16) var(--spacing-24); display: grid; grid-template-columns: repeat(2, minmax(260px, 1fr)); gap: 16px 24px; }
        .perm-card { border: 1px solid var(--border-light); border-radius: var(--radius-small); padding: 12px 12px; background: var(--bg-primary); }
        .perm-card .title { font-weight: 600; margin-bottom: 8px; color: var(--text-primary); }
        .perm-group { display: flex; flex-direction: column; gap: 8px; color: var(--text-secondary); }
        .radio-group { display: flex; gap: 12px; align-items: center; }

        /* 响应式 */
        @media (max-width: 768px) {
            .header { flex-wrap: wrap; padding: var(--spacing-12) var(--spacing-16); height: auto; }
            .header-spacer { width: 100%; justify-content: center; margin-bottom: 8px; }
            #app-nav { position: relative; left: 0; transform: none; width: 100%; order: 3; margin-top: var(--spacing-8); }
            .combined-header { flex-direction: column; align-items: flex-start; gap: var(--spacing-16); }
            .filter-container { flex-wrap: wrap; }
            .search-box { width: 100%; }
            .table-footer { flex-direction: column; gap: var(--spacing-16); align-items: flex-start; }
            .pagination-controls { flex-direction: column; gap: var(--spacing-16); align-items: flex-start; width: 100%; }
            .page-numbers { flex-wrap: wrap; }
            .perm-layout { grid-template-columns: 1fr; }
            .perm-left { height: 40%; border-right: none; border-bottom: 1px solid var(--border-light); }
            .perm-right { height: 60%; }
        }
    </style>
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            const { createApp, ref } = Vue;
            const navApp = createApp({
                setup() {
                    const activeIndex = ref('8');
                    const handleSelect = (key, keyPath) => { console.log(key, keyPath); };
                    return { activeIndex, handleSelect };
                }
            });
            navApp.use(ElementPlus, { locale: ElementPlusLocaleZhCn });
            navApp.mount('#app-nav');

            const userSection = document.getElementById('userSection');
            const userDropdown = document.getElementById('userDropdown');
            if (userSection && userDropdown) {
                userSection.addEventListener('click', function(e) {
                    e.stopPropagation();
                    const isOpen = userDropdown.style.display === 'block';
                    userDropdown.style.display = isOpen ? 'none' : 'block';
                });
                document.addEventListener('click', function() { userDropdown.style.display = 'none'; });
            }

            // 模拟数据
            const roles = [
                { id: 'r001', name: '系统管理员', desc: '系统最高权限管理员', created: '2025-08-01', status: 'enabled' },
                { id: 'r002', name: '医生', desc: '诊疗人员', created: '2025-08-01', status: 'enabled' },
                { id: 'r003', name: '护士', desc: '辅助医疗人员', created: '2025-08-01', status: 'enabled' },
                { id: 'r004', name: '数据分析', desc: '数据统计人员', created: '2025-08-01', status: 'disabled' }
            ];

            let filtered = [...roles];
            let pageSize = 10; let currentPage = 1; let totalPages = 1;

            // DOM
            const keywordEl = document.getElementById('keyword');
            const statusEl = document.getElementById('statusFilter');
            const queryBtn = document.getElementById('queryBtn');
            const resetBtn = document.getElementById('resetBtn');
            const createBtn = document.getElementById('createBtn');
            const bodyEl = document.getElementById('roleBody');
            const totalEl = document.getElementById('totalRecords');
            const pagesEl = document.getElementById('pageNumbers');
            const pageSizeEl = document.getElementById('pageSizeSelector');

            function renderTable() {
                const start = (currentPage - 1) * pageSize;
                const end = start + pageSize;
                const pageData = filtered.slice(start, end);
                bodyEl.innerHTML = '';
                if (pageData.length === 0) {
                    const row = document.createElement('tr');
                    row.innerHTML = `<td colspan="5" class="empty-table-message">暂无角色</td>`;
                    bodyEl.appendChild(row);
                } else {
                    pageData.forEach(r => {
                        const row = document.createElement('tr');
                        row.innerHTML = `
                            <td>${escapeHtml(r.name)}</td>
                            <td>${escapeHtml(r.desc)}</td>
                            <td>${r.created}</td>
                            <td>${r.status==='enabled'?'启用':'停用'}</td>
                            <td>
                                <div class="operations">
                                    <a class="operation-link" data-op="edit" data-id="${r.id}">编辑</a>
                                    <a class="operation-link" data-op="perm" data-id="${r.id}">权限管理</a>
                                    <a class="operation-link" data-op="delete" data-id="${r.id}" style="color: var(--error);">删除</a>
                                </div>
                            </td>`;
                        bodyEl.appendChild(row);
                    });
                }
                totalEl.textContent = filtered.length;
                renderPagination();
            }

            function renderPagination() {
                totalPages = Math.ceil(filtered.length / pageSize) || 1;
                pagesEl.innerHTML = '';
                let start = Math.max(1, currentPage - 2);
                let end = Math.min(totalPages, start + 4);
                if (end - start < 4 && totalPages > 4) start = Math.max(1, end - 4);
                for (let i = start; i <= end; i++) {
                    const btn = document.createElement('button');
                    btn.textContent = i; btn.className = i === currentPage ? 'active' : '';
                    btn.addEventListener('click', () => { currentPage = i; renderTable(); });
                    pagesEl.appendChild(btn);
                }
            }

            function applyFilter(){
                const kw = keywordEl.value.trim().toLowerCase();
                const st = statusEl.value;
                filtered = roles.filter(r => {
                    const matchKw = kw ? (r.name.toLowerCase().includes(kw) || r.desc.toLowerCase().includes(kw)) : true;
                    const matchSt = st==='all' ? true : (st==='enabled' ? r.status==='enabled' : r.status==='disabled');
                    return matchKw && matchSt;
                });
                currentPage = 1; renderTable();
            }

            function resetFilter(){
                keywordEl.value=''; statusEl.value='all'; filtered=[...roles]; currentPage=1; renderTable();
            }

            // 事件
            queryBtn.addEventListener('click', applyFilter);
            keywordEl.addEventListener('keypress', e => { if (e.key==='Enter') applyFilter(); });
            resetBtn.addEventListener('click', resetFilter);
            pageSizeEl.addEventListener('change', () => { pageSize = parseInt(pageSizeEl.value, 10); currentPage = 1; renderTable(); });

            // 代理操作
            document.addEventListener('click', function(e){
                const link = e.target.closest('a.operation-link');
                if (!link) return;
                const id = link.getAttribute('data-id');
                const op = link.getAttribute('data-op');
                if (op==='edit') openEdit(id);
                if (op==='delete') openDelete(id);
                if (op==='perm') openPerm(id);
            });

            // 编辑弹窗
            const editModal = document.getElementById('editModal');
            const closeEdit = document.getElementById('closeEdit');
            const cancelEdit = document.getElementById('cancelEdit');
            const saveEdit = document.getElementById('saveEdit');
            const roleName = document.getElementById('roleName');
            const roleDesc = document.getElementById('roleDesc');
            const statusEnabled = document.getElementById('statusEnabled');
            let editingId = null;
            createBtn.addEventListener('click', ()=> { editingId=null; roleName.value=''; roleDesc.value=''; statusEnabled.checked=true; editModal.style.display='flex'; });
            closeEdit.addEventListener('click', ()=> editModal.style.display='none');
            cancelEdit.addEventListener('click', ()=> editModal.style.display='none');
            editModal.addEventListener('click', e => { if (e.target===editModal) editModal.style.display='none'; });
            function openEdit(id){
                const r = roles.find(x => x.id===id); if (!r) return;
                editingId = id; roleName.value = r.name; roleDesc.value = r.desc; statusEnabled.checked = r.status==='enabled';
                editModal.style.display='flex';
            }
            saveEdit.addEventListener('click', ()=>{
                const name = roleName.value.trim(); if (!name) { alert('请输入角色名称'); return; }
                const desc = roleDesc.value.trim();
                if (editingId) {
                    const r = roles.find(x => x.id===editingId); if (r) { r.name=name; r.desc=desc; r.status = statusEnabled.checked ? 'enabled':'disabled'; }
                } else {
                    const id = 'r' + Math.random().toString().slice(2,6);
                    const now = new Date(); const pad=n=>String(n).padStart(2,'0');
                    const dt = `${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())}`;
                    roles.unshift({ id, name, desc, created: dt, status: statusEnabled.checked ? 'enabled':'disabled' });
                }
                editModal.style.display='none'; applyFilter();
            });

            // 删除确认
            const deleteModal = document.getElementById('deleteModal');
            const closeDelete = document.getElementById('closeDelete');
            const cancelDelete = document.getElementById('cancelDelete');
            const confirmDelete = document.getElementById('confirmDelete');
            let deleteId = null;
            function openDelete(id){ deleteId = id; deleteModal.style.display='flex'; }
            closeDelete.addEventListener('click', ()=> deleteModal.style.display='none');
            cancelDelete.addEventListener('click', ()=> deleteModal.style.display='none');
            deleteModal.addEventListener('click', e => { if (e.target===deleteModal) deleteModal.style.display='none'; });
            confirmDelete.addEventListener('click', ()=>{ if(deleteId){ const idx = roles.findIndex(n=>n.id===deleteId); if(idx>-1) roles.splice(idx,1); deleteModal.style.display='none'; applyFilter(); }});

            // 权限管理弹窗（全屏）
            const permModal = document.getElementById('permModal');
            const permTitle = document.getElementById('permTitle');
            const closePerm = document.getElementById('closePerm');
            const modulesEl = document.getElementById('modules');
            const permPanel = document.getElementById('permPanel');
            const dataScopeAll = document.getElementById('dataScopeAll');
            const dataScopeDept = document.getElementById('dataScopeDept');
            const dataScopeSelf = document.getElementById('dataScopeSelf');

            const modules = [
                { key: 'workbench', name: '诊断工作台', children: [
                    { key: 'start', name: '开始问诊' },
                    { key: 'record-query', name: '病历查询' },
                    { key: 'ai-diagnosis', name: 'AI辅助诊疗' },
                    { key: 'record-template', name: '病历模板管理' },
                    { key: 'personal-drug', name: '个人药品管理' }
                ]},
                { key: 'patient', name: '患者管理', children: [] },
                { key: 'statistics', name: '数据统计', children: [
                    { key: 'diag-stats', name: '诊断统计' },
                    { key: 'macro-stats', name: '宏观统计' }
                ]},
                { key: 'knowledge', name: '医学知识', children: [] },
                { key: 'basic-data', name: '基础数据', children: [
                    { key: 'drug-manage', name: '药品管理' }
                ]},
                { key: 'notice', name: '消息通知', children: [
                    { key: 'notice-view', name: '通知查看' },
                    { key: 'notice-publish', name: '通知发布' }
                ]},
                { key: 'user', name: '用户管理', children: [
                    { key: 'role-manage', name: '角色管理' }
                ]},
            ];

            let currentModuleKey = null;
            const permsByModule = {};
            function ensureModulePerm(key){
                if (!permsByModule[key]) {
                    permsByModule[key] = { view: false, create: false, edit: false, delete: false, dataScope: 'all' };
                }
                return permsByModule[key];
            }

            function renderModules(){
                modulesEl.innerHTML = '';
                const items = [];

                function renderNode(node, level = 0, parentKey = null) {
                    const hasChildren = Array.isArray(node.children) && node.children.length > 0;
                    const wrapper = document.createElement('div');
                    wrapper.className = 'tree-item';
                    wrapper.style.paddingLeft = (level * 16) + 'px';
                    wrapper.dataset.key = node.key;
                    if (parentKey) wrapper.dataset.parentKey = parentKey;

                    const arrow = document.createElement('span');
                    if (hasChildren) {
                        arrow.className = 'tree-arrow';
                        arrow.setAttribute('data-expanded', 'true');
                    } else {
                        arrow.className = 'tree-spacer';
                    }
                    const label = document.createElement('span');
                    label.textContent = node.name;

                    wrapper.appendChild(arrow);
                    wrapper.appendChild(label);
                    modulesEl.appendChild(wrapper);
                    items.push(wrapper);

                    wrapper.addEventListener('click', function(e){
                        const isArrow = e.target.classList.contains('tree-arrow');
                        if (isArrow && hasChildren) {
                            toggleNode(node.key);
                            e.stopPropagation();
                            return;
                        }
                        // 选中
                        items.forEach(el => el.classList.remove('active'));
                        wrapper.classList.add('active');
                        selectModule(node.key);
                    });

                    if (hasChildren) {
                        node.children.forEach(child => renderNode(child, level + 1, node.key));
                    }
                }

                function toggleNode(key) {
                    const parent = items.find(el => el.dataset.key === key);
                    if (!parent) return;
                    const arrow = parent.querySelector('.tree-arrow');
                    if (!arrow) return;
                    const expanded = arrow.getAttribute('data-expanded') === 'true';
                    arrow.setAttribute('data-expanded', expanded ? 'false' : 'true');
                    // 显示/隐藏直属子节点
                    items.forEach(el => {
                        if (el.dataset.parentKey === key) {
                            el.style.display = expanded ? 'none' : 'flex';
                            // 收起时递归隐藏后代
                            if (expanded) {
                                const childArrow = el.querySelector('.tree-arrow');
                                if (childArrow && childArrow.getAttribute('data-expanded') === 'true') {
                                    childArrow.setAttribute('data-expanded', 'false');
                                }
                                hideDescendants(el.dataset.key);
                            }
                        }
                    });
                }

                function hideDescendants(parentKey) {
                    items.forEach(el => {
                        if (el.dataset.parentKey === parentKey) {
                            el.style.display = 'none';
                            hideDescendants(el.dataset.key);
                        }
                    });
                }

                modules.forEach(m => renderNode(m, 0, null));
            }

            function selectModule(key){
                currentModuleKey = key;
                const current = ensureModulePerm(currentModuleKey);
                permPanel.innerHTML = '';
                const card1 = document.createElement('div'); card1.className='perm-card';
                card1.innerHTML = `<div class="title">操作权限</div>
                    <div class="perm-group">
                        <label><input type="checkbox" id="p_view"> 查看权限</label>
                        <label><input type="checkbox" id="p_create"> 新增权限</label>
                        <label><input type="checkbox" id="p_edit"> 编辑权限</label>
                        <label><input type="checkbox" id="p_delete"> 删除权限</label>
                    </div>`;
                const card2 = document.createElement('div'); card2.className='perm-card';
                card2.innerHTML = `<div class="title">数据权限</div>
                    <div class="radio-group">
                        <label><input type="radio" name="dataScope" value="all"> 全部数据</label>
                        <label><input type="radio" name="dataScope" value="self"> 个人数据</label>
                    </div>`;
                permPanel.appendChild(card1);
                permPanel.appendChild(card2);
                // 回显与绑定
                setTimeout(()=>{
                    const pv=document.getElementById('p_view'), pc=document.getElementById('p_create'), pe=document.getElementById('p_edit'), pd=document.getElementById('p_delete');
                    if(pv) { pv.checked = current.view; pv.addEventListener('change', ()=> ensureModulePerm(currentModuleKey).view = pv.checked); }
                    if(pc) { pc.checked = current.create; pc.addEventListener('change', ()=> ensureModulePerm(currentModuleKey).create = pc.checked); }
                    if(pe) { pe.checked = current.edit; pe.addEventListener('change', ()=> ensureModulePerm(currentModuleKey).edit = pe.checked); }
                    if(pd) { pd.checked = current.delete; pd.addEventListener('change', ()=> ensureModulePerm(currentModuleKey).delete = pd.checked); }
                    const radios = permPanel.querySelectorAll('input[name="dataScope"]');
                    radios.forEach(r => {
                        r.checked = (r.value === current.dataScope);
                        r.addEventListener('change', function(){ ensureModulePerm(currentModuleKey).dataScope = this.value; });
                    });
                }, 0);
            }

            function openPerm(id){
                const r = roles.find(x => x.id===id); if (!r) return;
                permTitle.textContent = `角色权限管理 - ${r.name}`;
                permModal.style.display='flex';
                if (!currentModuleKey) selectModule('workbench');
            }
            closePerm.addEventListener('click', ()=> permModal.style.display='none');
            permModal.addEventListener('click', e => { if (e.target===permModal) permModal.style.display='none'; });

            function escapeHtml(str){
                if (!str && str!==0) return '';
                return String(str).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;');
            }

            // 初始化
            renderModules();
            applyFilter();
        });
    </script>
</head>
<body>
    <div id="app" class="container">
        <header class="header">
            <div class="header-spacer"></div>
            <div id="app-nav">
                <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect" :ellipsis="false" :popper-offset="0" popper-class="custom-dropdown">
                    <el-menu-item index="1">开始问诊</el-menu-item>
                    <el-sub-menu index="2" popper-class="custom-dropdown">
                        <template #title>病历管理</template>
                        <el-menu-item index="2-1">病历查询</el-menu-item>
                        <el-menu-item index="2-2">病历模板</el-menu-item>
                        <el-menu-item index="2-3">个人药品</el-menu-item>
                    </el-sub-menu>
                    <el-menu-item index="3">患者管理</el-menu-item>
                    <el-sub-menu index="4" popper-class="custom-dropdown">
                        <template #title>数据统计</template>
                        <el-menu-item index="4-1">诊断统计</el-menu-item>
                        <el-menu-item index="4-2">宏观统计</el-menu-item>
                    </el-sub-menu>
                    <el-menu-item index="5">医学知识</el-menu-item>
                    <el-sub-menu index="6" popper-class="custom-dropdown">
                        <template #title>基础数据</template>
                        <el-menu-item index="6-1">药品管理</el-menu-item>
                    </el-sub-menu>
                    <el-sub-menu index="7" popper-class="custom-dropdown">
                        <template #title>消息通知</template>
                        <el-menu-item index="7-1">通知查看</el-menu-item>
                        <el-menu-item index="7-2">通知发布</el-menu-item>
                    </el-sub-menu>
                    <el-sub-menu index="8" popper-class="custom-dropdown">
                        <template #title>用户管理</template>
                        <el-menu-item index="8-1">角色管理</el-menu-item>
                    </el-sub-menu>
                </el-menu>
            </div>
            <div class="user-section" id="userSection">
                <span class="user-name">管理员</span>
                <svg class="user-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>
            </div>
            <div class="user-dropdown" id="userDropdown" style="display:none; position:absolute; top:60px; right:24px; width:160px; background:#fff; border:1px solid var(--border-light); border-radius:2px; box-shadow:0 4px 12px rgba(0,0,0,0.08); overflow:hidden; z-index:200;">
                <div class="item" style="padding:10px 12px; color:var(--text-secondary); cursor:pointer;">个人中心</div>
                <div class="item" style="padding:10px 12px; color:var(--text-secondary); cursor:pointer;">退出登录</div>
            </div>
        </header>

        <div class="main-content">
            <section class="combined-header">
                <h1 class="page-title">角色管理</h1>
                <div class="filter-container">
                    <div class="search-box">
                        <svg class="search-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
                        <input id="keyword" type="text" placeholder="搜索角色...">
                    </div>
                    <select id="statusFilter" class="select">
                        <option value="all">角色状态: 全部</option>
                        <option value="enabled">启用</option>
                        <option value="disabled">停用</option>
                    </select>
                    <button id="queryBtn" class="btn btn-primary">查询</button>
                    <button id="resetBtn" class="btn btn-default">重置</button>
                    <button id="createBtn" class="btn btn-primary">新建角色</button>
                </div>
            </section>

            <section class="table-section">
                <div class="table-container">
                    <table class="data-table">
                        <thead>
                            <tr>
                                <th>角色名称</th>
                                <th>角色描述</th>
                                <th>创建时间</th>
                                <th>状态</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody id="roleBody"></tbody>
                    </table>
                </div>
                <div class="table-footer">
                    <div class="pagination-text">共 <span id="totalRecords">0</span> 条记录</div>
                    <div class="pagination-controls">
                        <div id="pageNumbers" class="page-numbers"></div>
                        <div class="pagination-size">
                            每页显示
                            <select id="pageSizeSelector" class="page-size-selector">
                                <option value="10">10</option>
                                <option value="20">20</option>
                                <option value="50">50</option>
                            </select>
                            条
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </div>

    <!-- 角色编辑弹窗 -->
    <div id="editModal" class="modal-overlay">
        <div class="modal" style="width: 560px;">
            <div class="modal-header">
                <h3 class="modal-title">编辑角色</h3>
                <button class="modal-close" id="closeEdit">×</button>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label class="form-label" for="roleName">角色名称</label>
                    <input id="roleName" class="form-control" placeholder="请输入角色名称">
                </div>
                <div class="form-group">
                    <label class="form-label" for="roleDesc">角色描述</label>
                    <textarea id="roleDesc" class="form-control" placeholder="请输入角色描述"></textarea>
                </div>
                <div class="form-group">
                    <label class="form-label">角色状态</label>
                    <div style="display:flex; gap:16px; align-items:center;">
                        <label style="display:flex; gap:8px; align-items:center;"><input id="statusEnabled" type="radio" name="roleStatus" value="enabled" checked> 启用</label>
                        <label style="display:flex; gap:8px; align-items:center;"><input type="radio" name="roleStatus" value="disabled"> 停用</label>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn btn-default" id="cancelEdit">取消</button>
                <button class="btn btn-primary" id="saveEdit">保存</button>
            </div>
        </div>
    </div>

    <!-- 删除确认弹窗 -->
    <div id="deleteModal" class="modal-overlay">
        <div class="modal" style="width: 420px;">
            <div class="modal-header">
                <h3 class="modal-title">确认删除</h3>
                <button class="modal-close" id="closeDelete">×</button>
            </div>
            <div class="modal-body">
                <div style="text-align:center; color:var(--text-primary); margin-bottom:8px;">确定要删除该角色吗？</div>
                <div style="text-align:center; color:var(--text-tertiary); font-size:12px;">该操作不可恢复</div>
            </div>
            <div class="modal-footer">
                <button class="btn btn-default" id="cancelDelete">取消</button>
                <button class="btn btn-primary" id="confirmDelete">确定删除</button>
            </div>
        </div>
    </div>

    <!-- 权限管理（全屏） -->
    <div id="permModal" class="modal-overlay">
        <div class="modal fullscreen">
            <div class="perm-header">
                <h3 class="modal-title" id="permTitle">角色权限管理</h3>
                <button class="modal-close" id="closePerm">×</button>
            </div>
            <div class="perm-layout">
                <div class="perm-left">
                    <div id="modules" class="tree"></div>
                </div>
                <div class="perm-right">
                    <div id="permPanel" class="perm-section"></div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>


